/*
 * Policy Engine Model (Evaluator)
 * @author: Kshitij Dogra
 * @date: Apr 21, 2012		
 */

#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include "policy.h"
#include "nm.h"
#include "lm.h"
using namespace std;

class Interface
{
    public:
    int interfaceEval(char* interface);
    int interfaceStatus(char* interface);
};

int Interface::interfaceEval(char*interface)
{
    char* inter=new char[15];
    int j=0;
    for(int i=0;i<=strlen(interface);i++)
    {
        if(interface[i]!=' ' && interface[i]!='\0')
        {
            inter[j]=interface[i];
            j++;
        }
        else
        {
            j++;
            inter[j]='\0';
            int ret=interfaceStatus(inter);
            if(!ret)
                return 0;       // make it zero
            memset(inter,0,15);
            j=0;
        }
    }
    delete inter;
    return 1;
}

int Interface::interfaceStatus(char* interface)
{
        char* buffer=new char[10];
	memset (buffer,0,10);
	sine_getIfStatus(desInt, buffer);
	if(!strcmp(buffer, "up"))
		return 1;
    	else
    		return 0;
    
    /*	if(!strcmp(interface,"wlan0"))
		return 1;
		else
		return 0;
    */	
}

class Location
{
    int resolveLocation(char* location);
    int locationStatus(char* location);
};

int Location::resolveLocation(char* location)
{
    char* loc = new char[15];
    int j=0;
    for(int i=0;i<strlen(location);i++)
    {
	if(location[i]!=' ' && location[i]!='\0')
	{
	    loc[j]=location[i];
	    j++;
	}
	else
	{
	   j++;
	   loc[j]='\0';
	   int ret=locationStatus(loc);
	   if(!ret)
		return 0;
	   memset(loc,0,15);   
	   j=0	
	}
    }
    delete loc;
    return 1;			
}

int Location::locationStatus(char* location)
{
   char* obtLoc=new char[20];
   memset(obtLoc,0,15);
   sine_getLocation(obtLoc);
   if(!strcmp(obtLoc, location))
	  return 1;
   else
	  return 0;		
}

class Bandwidth
{
    public:
    int resolveBandwidth(int band);
};

int Bandwidth::resolveBandwidth(int band)
{
    int obtBand=510;
    obtBand = sine_getBandwidth(interfaces[interfaceIndex]);
    //obtBand=atoi(strBand);
    if(band<=obtBand)
        return 1;
    else
        return 0;
}

class Cost
{
    public:
    int resolveCost(int cost);
};

int Cost::resolveCost(int cost)
{
    int obtCost=10;
    obtCost = sine_getCost(interfaces[interfaceIndex]);
    //obtCost=atoi(strCost);
    if(cost>=obtCost)
        return 1;
    else
        return 0;
}

class DownloadLimit
{
    int resolvedwnLimit(int dwnlimit);
};

class ConditionList
{
    public:
    Location* location;
    Bandwidth* bandwidth;
    Cost* cost;
    DownloadLimit* dwnLimit;
};

class Action
{
    public:
    char* interface;
};

class Rules     // Similar to Conditions
{
    public:
    ConditionList* condList;
    Action* action;
};

class Policy
{
    public:
    int policyID;
    int appID;
    Rules* rule;
};

char* policyModel(int, int);

/*
int main()
{
    char* interfaces=policyModel(77,1000);
    if(interfaces==NULL)
        cout<<"No available interfaces";
    else
        cout<<interfaces;
    return 0;
}*/

char* policyModel(int appID, int sockfd)
{
    ifstream in("configPolicy.txt"); // input
    if(!in) {
        cout << "Cannot open input file.\n";
        return NULL;
    }

    char str[255];
    char*strAppID = new char[5];
    while(in)
    {
        in.getline(str, 255);
        int dataIndex=0;
        unsigned int i=0;
       	for(i=0;i<strlen(str);i++)
   		{
            if(str[i]!=','){
           		strAppID[dataIndex]=str[i];
       			dataIndex++;
            }
	        else{
	             strAppID[dataIndex]='\0';
	             break;
	        }
    	}
    	int appIDSearch=atoi(strAppID);
    	if(appIDSearch!=appID)
            continue;
        else
        {
            delete strAppID;
            //cout<<"Working for appID "<<appIDSearch<<endl;
            Policy* policy=new Policy;
            policy->appID=appIDSearch;
            char* rCount=new char[1];
            rCount[0]=str[i+1];
            int ruleCount=atoi(rCount);
            delete rCount;
            Rules* rules=new Rules[ruleCount];      // Set the # of rules.
            policy->rule=rules;

            for(int j=0;j<ruleCount;j++)        // looping for each condition
            {
                dataIndex=0;
                in.getline(str, 255);
                char*strCondCount = new char[5];
                for(i=0;i<strlen(str);i++)
                {
                    if(str[i]!=','){
                        strCondCount[dataIndex]=str[i];
                        dataIndex++;
                    }
                    else{
                        strCondCount[dataIndex]='\0';
                        break;
                    }
                }
                int condCount = atoi(strCondCount);
                delete strCondCount;
                char* interfaces = new char[20];      // Do not delete this pointer
                int interIndex=0;
                i++;
                while(i<strlen(str))
                {
                    interfaces[interIndex]=str[i];
                    i++;
                    interIndex++;
                }
                interfaces[interIndex]='\0';

                Action* act=new Action; // Assigning actions to rules and itnerfaces to actions.
                ConditionList* cl=new ConditionList[condCount];
                rules[j].action=act;
                rules[j].condList=cl;
                Interface* obj = new Interface;
                act->interface=interfaces;
                if(!(obj->interfaceEval(interfaces)))
                {
                    for(int i=0;i<condCount;i++)
                        in.getline(str, 255);
                     continue;
                }

                // Now loop for condCount
                for(int i=0;i<condCount;i++)
                {
                     in.getline(str, 255);
                     char* strLocation = new char[30];           // This is to extract the location.
                     dataIndex=0;
                     int condOffest=0;
                     for(condOffest=0;condOffest<strlen(str);condOffest++)
                     {
                        if(str[condOffest]!=','){
                            strLocation[dataIndex]=str[condOffest];
                            dataIndex++;
                        }
                        else{
                            strLocation[dataIndex]='\0';
                            break;
                        }
                     }
                     cl->location=new Location;                   // Do not delete strLocation -> memory leak.
               /*      if(!((cl->location)->resolveLocation(strLocation)))
                        continue;
                */
                     delete cl->location;
                     char*strBandwidth = new char[5];           // This is to extract the bandwidth.
                     dataIndex=0;
                     condOffest++;
                     for(;condOffest<strlen(str);condOffest++)
                     {
                         if(str[condOffest]!=','){
                             strBandwidth[dataIndex]=str[condOffest];
                             dataIndex++;
                         }
                         else{
                             strBandwidth[dataIndex]='\0';
                             break;
                         }
                      }
                     int bandwidth = atoi(strBandwidth);
                     delete strBandwidth;
                     cl->bandwidth=new Bandwidth;
                     if(!((cl->bandwidth)->resolveBandwidth(bandwidth)))
                        continue;
                     delete cl->bandwidth;

                     char*strCost = new char[5];           // This is to extract the cost.
                     dataIndex=0;
                     condOffest++;
                     for(;condOffest<strlen(str);condOffest++)
                     {
                         if(str[condOffest]!=','){
                             strCost[dataIndex]=str[condOffest];
                             dataIndex++;
                         }
                         else{
                             strCost[dataIndex]='\0';
                             break;
                         }
                      }
                     int cost = atoi(strCost);
                     delete strCost;
                     cl->cost=new Cost;
                     if(!((cl->cost)->resolveCost(cost)))
                        continue;
                    delete cl->cost;

                     char*strDwnLimit = new char[5];           // This is to extract the downloadLimit.
                     dataIndex=0;
                     condOffest++;
                     for(condOffest=0;i<strlen(str);condOffest++)
                     {
                         if(str[condOffest]!=','){
                             strDwnLimit[dataIndex]=str[condOffest];
                             dataIndex++;
                         }
                         else{
                             strDwnLimit[dataIndex]='\0';
                             break;
                         }
                      }
                     int download = atoi(strDwnLimit);
                     delete strDwnLimit;
                     cl->dwnLimit=new DownloadLimit;
           /*          if(!((cl->dwnLimit)->resolvedwnLimit(download)))
                        continue;
            */
                     delete cl->dwnLimit;
                     sine_setHipIf(sockfd, act->interface);
                     return act->interface;

                }   // Condition loop ends
            }
            return NULL;
        }   // else ends (I am checking the right policy)
    }   // while ends
}   // function returns
